
/**
 * Write a description of class player here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Player extends Character
{
    // instance variables - replace the example below with your own
    private int maxWeight;
    private int maxHealth;


    /**
     * Constructor for objects of class player
     * @param name The name of the player
     * @param maxWeight The maximum weight the player can carry
     * @param health The player's initial health pool
     * @param maxHealth the max amount of health the player can have
     * @param startRoom The room the player starts in.
     */
    public Player(String name, int maxWeight, int health, int maxHealth, Room startRoom)
    {
        super(name, health, startRoom);
        this.maxWeight = maxWeight;
        this.maxHealth = maxHealth;
        
    }

    //PUBLIC FUNCTIONS
    
    /**
     * Heals the player for a given amount, if he isn't healed already.
     * Can not heal above the player's maximum health
     * @param amountToHeal the amount to heal the player with
     */
    public String heal(int amountToHeal)
    {
        int newHealth = health + amountToHeal;
        
        //if the player is already fully healed
        if(health == maxHealth)
        {
            return "your health is already full!";
        }
        
        //if the heal would give him more health then his max, set the health to his max health instead.
        if (newHealth > maxHealth)
        {
            health = maxHealth;
        }
        else
        {
            health = newHealth;
        }
        
        return "you healed for " + amountToHeal + ", your new health is " + health;
        
    }
    
    /**
     * Adds an item to the inventory. Takes the maximum weight into account
     * @param item The item to add
     */
    public boolean addToInventory(Item item)
    {
        if(checkWeight(item.getWeight()))
        {
            inventory.put(item.getName(), item);
            System.out.println();
            System.out.println ("you picked up: " + item.getName());
            System.out.println();
            return true;
        }
        else
        {
            System.out.println();
            System.out.println("it's too heavy!");
            System.out.println();
            return false;
        }
        
    }
    
    /**
     * Take an item from a room's inventory and put it in the player's inventory
     * @param itemName The name of the item to move
     */
    public boolean getItemFromRoom(String itemName)
    {
        if(!currentRoom.hasItem(itemName))
        {
            return false;
        }
        
        //add the item to the player's inventory
        if(addToInventory(currentRoom.getItem(itemName)))
        {
            //remove the item from the room's inventory
            currentRoom.removeItem(itemName);
        }
        
        return true;
    }
    
    //PRIVATE FUNCTIONS
    /**
     * check if the weight of an item does not make the player's inventory too heavy
     * @param weightToAdd The weight of the item you want to add.
     */
    private boolean checkWeight(int weightToAdd)
    {
        int totalWeight = getTotalInventoryWeight();
        if ((totalWeight + weightToAdd) > maxWeight)
        {
            return false;
        }
        
        return true;
    }
    
    /**
     * Calculate how much weight the inventory has.
     */
    public int getTotalInventoryWeight()
    {
        int totalWeight = 0;
        for(String currentItem : inventory.keySet())
        {
            totalWeight += inventory.get(currentItem).getWeight();
        }
        
        return totalWeight;
    }
    
    /**
     * Get a list of all items in the current room
     */
    public String getItemsInRoom()
    {
        return currentRoom.getItemOverview();
    }
    
    /**
     * Get the room that is in a specific direction
     * @param direction The direction the room you want to get is in.
     */
    public Room getExit(String direction)
    {
        return currentRoom.getExit(direction);
    }
    
    /**
     * Check if the exit in a given direction is locked or not
     * @param direction the direction you want to know the locked status of
     */
    public String isExitLocked(String direction)
    {
        return currentRoom.isDoorLocked(direction);
    }
    
    /**
     * unlocks a direction, using an item
     * @param direction The direction you want to unlock
     * @param item The name of the item you want to open the door with.
     */
    public boolean unlock(String direction, String item)
    {
        return currentRoom.unlock(direction, item);
    }
    
    /**
     * Eat an item, regaining health
     * @param itemToEat The name of the item you want to eat.
     */
    public String eatItem(String itemToEat)
    {
        Item itemToBeEaten = inventory.get(itemToEat);
        if(itemToBeEaten instanceof Consumeable)
        {
            String result = heal(getItemStrength(itemToEat));
            removeItem(itemToEat);
            
            return result;
        }
        else
        {
            return "you can't eat that item! it's a " + itemToEat;
        }
    }
    
    /**
     * Remind the player that talking to yourself is bad. (unless it's introspection)
     */
    public String talk()
    {
        return "Talking to yourself already?";
    }
    
    /**
     * Attack the enemy in the current room.
     * If he is not killed, the enemy will retaliate
     */
    public String attack()
    {
        //get the amount of damage the player's highest damage-dealing item does.
        int damageDone = getStrongestWeaponDamage();
        
        if(damageDone == 0)
        {
            System.out.println();
            System.out.println("You have no weapons!");
            System.out.println();
            return "";
        }
        
        //is there a monster to attack?
        if(currentRoom.getMonster() == null)
        {
            System.out.println();
            System.out.println("there is nothing to attack");
            System.out.println();
            return "";
        }
        //if it is, attack.
        Monster monster = currentRoom.getMonster();
        monster.takeDamage(damageDone);
        
        System.out.println("You have dealt " + damageDone + " damage to " + monster.getName());
        
        //if the monster died, print a message. else, it will retaliate
        if(monster.getHealth() <= 0)
        {
            currentRoom.monsterDefeated();
            
            if(monster instanceof Boss){
                return "victory boss";
            }
            else{
                return "victory monster";
            }
        }
        else
        {
            //attack player.
            int damageTaken = monster.getDamage();
            System.out.println("The monster retaliates! you take " + monster.getDamage() + " damage.");

            System.out.println();
            
            takeDamage(damageTaken);
            
            //if the player is killed...
            if(health <= 0)
            {
                System.out.println();
                System.out.println("You were defeated.");
                System.out.println();
                return("defeat");
            }
            
            //if neither the player or the monster were killed
            return("combat");
        }
    }
    
    //PRIVATE FUNCTIES
    
    /**
     * Get the strongest weapon the player has in it's 
     */
    private int getStrongestWeaponDamage()
    {
        int highestDamageFound = 0;
        
        //for every weapon in the inventory
        for(Item item : inventory.values())
        {
            if(item instanceof Weapon)
            {
                //get it's damage and compare it to the current highest damage found.
                int currentWeaponDamage = item.getStrength();
                if(currentWeaponDamage > highestDamageFound)
                {
                    highestDamageFound = currentWeaponDamage;
                }
            }
        }
        
        return highestDamageFound;
    }
    
    
    
    // GETTERS
    
    /**
     * Get the player's max health
     */
    public int getMaxHealth()
    {
        return maxHealth;
    }
    
    /**
     * Get the maximum weight a player can carry
     */
    public int getMaxWeight()
    {
        return maxWeight;
    }
    
    
    
    // SETTERS
    
    /**
     * Set the player's new maximum health
     * @param newMaxHealth The player's new maximum health
     */
    public void setMaxHealth(int newMaxHealth)
    {
        maxHealth = newMaxHealth;
    }
    
    /**
     * Set the player's new maximum weight
     * @param newMaxWeight The player's new maximum weight
     */
    public void getMaxWeight(int newMaxWeight)
    {
        maxWeight = newMaxWeight;
    }
}